Menu

Hello 👋,
how can we help you?

If you have any questions or need help, please don't hesitate to contact us.

🟢 Chat with our assistant Tell us your case

This might be useful

Fisioterapia para Músicos

Introducción a la Fisioterapia para Músicos

La fisioterapia especializada para músicos es más que un tratamiento; es un viaje hacia la armonía entre cuerpo y música. Al comprender las demandas únicas que la música impone en el cuerpo, en eFISIO, ofrecemos un enfoque personalizado para abordar tanto las lesiones como las preocupaciones preventivas.

Ya seas un pianista, un violinista o un percusionista, cada movimiento, postura y técnica que empleas tiene un impacto en tu cuerpo. La prevención y el tratamiento de lesiones son cruciales en tu carrera. Por ello, nuestra fisioterapia para músicos está diseñada para mejorar tu rendimiento y bienestar a través de técnicas específicas adaptadas a tus necesidades.

En eFISIO, creemos en el poder de una recuperación integral. No solo nos enfocamos en el alivio del dolor o la rehabilitación de lesiones, sino también en la optimización de tu capacidad de tocar. Esto incluye desde el manejo de problemas de suelo pélvico hasta la mejora de la respiración y la postura, elementos clave en la ejecución musical.

Para más información sobre cómo podemos ayudarte, explora nuestra sección de .

Técnicas de Fisioterapia Utilizadas con Músicos

En eFISIO, aplicamos una variedad de técnicas de fisioterapia especializadas adaptadas a las necesidades únicas de los músicos. Una de las más importantes es la terapia manual, que incluye masajes, movilizaciones y manipulaciones para aliviar el dolor, mejorar la movilidad y prevenir lesiones.

Otra técnica fundamental es la reeducación postural. Muchos músicos sufren problemas derivados de posturas mantenidas durante largos períodos. Aquí, nos enfocamos en mejorar la alineación corporal y enseñar técnicas de postura adecuadas para minimizar el riesgo de lesiones y mejorar la comodidad al tocar.

Además, utilizamos ejercicios específicos de fortalecimiento y estiramiento diseñados para las necesidades particulares de cada músico. Estos ejercicios no solo ayudan en la recuperación de lesiones, sino que también juegan un papel crucial en la prevención de problemas futuros.

Para músicos que buscan una recuperación más profunda, ofrecemos tecnicas de relajación y manejo del estrés, vitales para mantener un equilibrio mental y físico. Estas técnicas incluyen la respiración diafragmática, la relajación muscular progresiva y la mindfulness, todas cruciales para el bienestar general de un músico.

Explora más sobre cómo podemos ayudarte en nuestra sección de .

Cómo la Fisioterapia Puede Ayudar a Pianistas y Otros Instrumentistas

La fisioterapia juega un papel esencial en el bienestar de pianistas y otros instrumentistas. En eFISIO, nos enfocamos en abordar las lesiones específicas que afectan a estos artistas, como tendinitis, dolor de espalda y problemas de cuello, todos resultado de largas horas de práctica y posturas poco ergonómicas.

Una parte crucial de nuestro enfoque es la reeducación postural. Trabajamos con músicos para desarrollar una postura que no solo prevenga lesiones sino que también mejore la eficiencia y comodidad al tocar. Esto es especialmente importante para pianistas, que a menudo sufren de problemas relacionados con posturas estáticas y movimientos repetitivos.

Nuestro tratamiento también incluye técnicas de fortalecimiento y estiramiento. Estas técnicas están diseñadas para aumentar la resistencia muscular y la flexibilidad, permitiendo a los músicos tocar con más facilidad y menor riesgo de lesiones. Estas prácticas son fundamentales para instrumentistas que requieren un alto grado de control y precisión en sus movimientos.

Además, ofrecemos terapias de relajación y manejo del dolor, que son esenciales para lidiar con el estrés físico y mental que enfrentan los músicos. Técnicas como la termoterapia, la electroterapia o la masoterapia pueden ser extremadamente beneficiosas para aliviar la tensión muscular y mejorar la calidad general de la ejecución musical.

Si eres un pianista o instrumentista buscando apoyo, descubre cómo podemos ayudarte en .

El Papel de eFISIO en la Fisioterapia para Músicos en Madrid

En eFISIO, nos hemos posicionado como un referente en fisioterapia para músicos en Madrid. Con un profundo entendimiento de las necesidades específicas de los artistas, proporcionamos un enfoque personalizado que va más allá del tratamiento de lesiones. Nuestro objetivo es mejorar tu bienestar general y asegurar que tu cuerpo y tu música estén en perfecta armonía.

Nuestra clínica cuenta con fisioterapeutas especializados en trabajar con músicos, ofreciendo tratamientos y técnicas adaptadas a las exigencias físicas de tocar un instrumento. Desde la terapia manual hasta programas de ejercicios personalizados, nos enfocamos en prevenir lesiones y mejorar la calidad de vida de nuestros pacientes.

Además de tratamientos individuales, en eFISIO también ofrecemos workshops y charlas educativas para músicos, abordando temas como la ergonomía en la práctica musical, técnicas de calentamiento y estrategias para gestionar el estrés. Estos eventos son una oportunidad para que los músicos de Madrid se conecten y aprendan cómo cuidar mejor de su salud mientras persiguen su pasión.

Para conocer más sobre cómo podemos asistirte en tu viaje musical, explora nuestros servicios en ", { class: "eflexbar efisio_adminbar", }); for (var i = 0; i < links.length; i++) { var link = $("", { href: links[i][1], text: links[i][0], }); topbar.append(link); } topbar.append(link); $("body").prepend(topbar); } // get userinfo cookie var userinfo = getCookie("userinfo"); // if not set fetch json from /api/users/userinfo if (userinfo === undefined) { /*$.getJSON("/api/users/userinfo", function (data) { setCookie("userinfo", JSON.stringify(data), 1000); if (data.role && data.role.length) { add_topbar(data.links); } });*/ } else { userinfo = JSON.parse(userinfo); if (userinfo.role && userinfo.role.length) { add_topbar(userinfo.links); } } }); document.addEventListener("DOMContentLoaded", function() { var $ = jQuery; function grantedCookies() { if (areAdvertisementCookiesAccepted()) { if (typeof gtag !== "undefined") gtag("consent", "update", { ad_user_data: "granted", ad_personalization: "granted", ad_storage: "granted", analytics_storage: "granted", }); } } if (isMobileApp()) return; if (!checkCookieConsent()) { showCookieBanner(); } else { grantedCookies(); } function showCookieBanner() { // Inject styles const style = document.createElement("style"); style.textContent = ` .cc-banner { position: fixed; bottom: 0; left: 0; right: 0; z-index: 99999; padding: 1rem; display: flex; justify-content: center; opacity: 0; transform: translateY(1rem); transition: opacity 0.3s, transform 0.3s; pointer-events: none; } .cc-banner.cc-visible { opacity: 1; transform: translateY(0); pointer-events: auto; } .cc-card { background: var(--bg0, #fff); border: 1px solid #e5e7eb; border-radius: 1rem; box-shadow: 0 -4px 30px rgba(0,0,0,0.1); padding: 1.25rem 1.5rem; max-width: 640px; width: 100%; } .cc-body { display: flex; align-items: flex-start; gap: 0.75rem; margin-bottom: 1rem; } .cc-icon { flex-shrink: 0; font-size: 1.5rem; color: var(--primary-color, #009999); margin-top: 2px; } .cc-text { font-size: 0.85rem; line-height: 1.5; color: var(--text-color, #374151); margin: 0; } .cc-link { color: var(--primary-color, #009999); text-decoration: underline; text-underline-offset: 2px; } .cc-link:hover { color: var(--primary-dark, #007a7a); } .cc-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; } .cc-btn { padding: 0.5rem 1rem; border-radius: 0.5rem; font-size: 0.85rem; font-weight: 500; cursor: pointer; border: none; transition: background 0.15s, box-shadow 0.15s; } .cc-btn-primary { background: var(--primary-color, #009999); color: #fff; } .cc-btn-primary:hover { background: var(--primary-dark, #007a7a); box-shadow: 0 2px 8px rgba(0,153,153,0.3); } .cc-btn-ghost { background: transparent; color: var(--text-color, #6b7280); border: 1px solid #d1d5db; } .cc-btn-ghost:hover { background: #f3f4f6; border-color: #9ca3af; } @media (max-width: 480px) { .cc-card { padding: 1rem; } .cc-actions { flex-direction: column; } .cc-btn { width: 100%; text-align: center; } .cc-body { flex-direction: column; align-items: center; text-align: center; } } `; document.head.appendChild(style); const banner = document.createElement("div"); banner.className = "cc-banner"; banner.innerHTML = `

`; document.body.appendChild(banner); requestAnimationFrame(() => banner.classList.add("cc-visible")); banner.addEventListener("click", function(e) { const action = e.target.dataset.cc; if (!action) return; if (action === "all") consentCookies(); else if (action === "necessary") consentNecessaryCookies(); else if (action === "reject") rejectCookies(); banner.classList.remove("cc-visible"); setTimeout(() => banner.remove(), 300); $(document).trigger("grantedCookies"); }); } function consentCookies() { setCookieConsent({ necessary: true, functional: true, performance: true, analytics: true, advertisement: true, others: true, }); grantedCookies(); } function consentNecessaryCookies() { setCookieConsent({ necessary: true, functional: false, performance: false, analytics: false, advertisement: false, others: false, }); grantedCookies(); } function rejectCookies() { setCookieConsent({ necessary: false, functional: false, performance: false, analytics: false, advertisement: false, others: false, }); } }); function format_date(datestr) { // Format date const date = new Date(datestr); const day = date.getDate(); const month = date.getMonth() + 1; const year = date.getFullYear(); const hours = date.getHours(); const minutes = date.getMinutes(); const seconds = date.getSeconds(); const formattedDate = `${day.toString().padStart(2, "0")}-${month .toString() .padStart(2, "0")}-${year} ${hours.toString().padStart(2, "0")}:${minutes .toString() .padStart(2, "0")}`; return formattedDate; } function diabonito(timestamp, flag) { let date; // Check if timestamp is in "YYYY-MM-DD" format if (typeof timestamp === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(timestamp)) { // If timestamp is a date string, directly create a Date object from it date = new Date(timestamp); } else { // Otherwise, assume timestamp is a UNIX timestamp in seconds and convert to milliseconds date = new Date(parseInt(timestamp) * 1000); } // Format options for date parts const optionsWeekday = { weekday: 'long', timeZone: 'Europe/Madrid' }; const optionsDayMonth = { day: 'numeric', month: 'long', timeZone: 'Europe/Madrid' }; // Getting localized strings for each part with Madrid timezone const weekday = date.toLocaleDateString('es-ES', optionsWeekday); const dayMonth = date.toLocaleDateString('es-ES', optionsDayMonth); // Concatenating the parts return `${weekday}, ${dayMonth}`; } /** * Enhanced Tracking System * Captures comprehensive source attribution and conversion details */ var EnhancedTracking = (function() { 'use strict'; /** * Extract source parameters from URL with enhanced campaign tracking */ function getSourceParams() { const params = new URLSearchParams(window.location.search); const sourceData = { // UTM parameters utm_source: params.get('utm_source') || '', utm_medium: params.get('utm_medium') || '', utm_campaign: params.get('utm_campaign') || '', utm_term: params.get('utm_term') || '', utm_content: params.get('utm_content') || '', utm_id: params.get('utm_id') || '', // Campaign ID // Platform-specific parameters gclid: params.get('gclid') || '', // Google Ads Click ID gbraid: params.get('gbraid') || '', // Google Ads App conversion wbraid: params.get('wbraid') || '', // Google Ads Web conversion fbclid: params.get('fbclid') || '', // Facebook Click ID msclkid: params.get('msclkid') || '', // Microsoft/Bing twclid: params.get('twclid') || '', // Twitter ttclid: params.get('ttclid') || '', // TikTok li_fat_id: params.get('li_fat_id') || '', // LinkedIn epik: params.get('epik') || '', // Pinterest gmb: params.get('gmb') || '', // Google My Business // Google Ads specific campaignid: params.get('campaignid') || '', adgroupid: params.get('adgroupid') || '', feeditemid: params.get('feeditemid') || '', targetid: params.get('targetid') || '', loc_interest_ms: params.get('loc_interest_ms') || '', loc_physical_ms: params.get('loc_physical_ms') || '', devicemodel: params.get('devicemodel') || '', creative: params.get('creative') || '', keyword: params.get('keyword') || '', matchtype: params.get('matchtype') || '', network: params.get('network') || '', device: params.get('device') || '', placement: params.get('placement') || '', // Facebook/Meta specific fb_campaign_id: params.get('fb_campaign_id') || '', fb_adset_id: params.get('fb_adset_id') || '', fb_ad_id: params.get('fb_ad_id') || '', fb_placement: params.get('fb_placement') || '', fb_product_id: params.get('fb_product_id') || '', // Additional tracking ref: params.get('ref') || '', source: params.get('source') || '' }; // Clean empty values Object.keys(sourceData).forEach(key => { if (!sourceData[key]) delete sourceData[key]; }); return sourceData; } /** * Get or create session ID */ function getSessionId() { let sessionId = sessionStorage.getItem('efisio_session_id'); if (!sessionId) { sessionId = 'sess_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); sessionStorage.setItem('efisio_session_id', sessionId); } return sessionId; } /** * Store source attribution data */ function storeSourceAttribution() { const sourceParams = getSourceParams(); // Only store if we have source data if (Object.keys(sourceParams).length > 0) { // Store in session storage for current session sessionStorage.setItem('efisio_source_params', JSON.stringify(sourceParams)); // Store timestamp sessionStorage.setItem('efisio_source_timestamp', Date.now().toString()); // If it's the first visit, also store in localStorage if (!localStorage.getItem('efisio_first_source')) { localStorage.setItem('efisio_first_source', JSON.stringify(sourceParams)); localStorage.setItem('efisio_first_source_timestamp', Date.now().toString()); } } } /** * Get current source attribution */ function getSourceAttribution() { // Try session storage first (most recent) let source = sessionStorage.getItem('efisio_source_params'); if (source) { return JSON.parse(source); } // Fall back to first source source = localStorage.getItem('efisio_first_source'); if (source) { return JSON.parse(source); } // Check current URL const currentParams = getSourceParams(); if (Object.keys(currentParams).length > 0) { return currentParams; } return null; } /** * Determine source/medium from attribution data */ function determineSourceMedium(attribution) { if (!attribution) return { source: 'direct', medium: 'none' }; // UTM takes priority if (attribution.utm_source) { return { source: attribution.utm_source, medium: attribution.utm_medium || 'unknown' }; } // Platform-specific if (attribution.gclid) return { source: 'google', medium: 'cpc' }; if (attribution.fbclid) return { source: 'facebook', medium: 'social' }; if (attribution.msclkid) return { source: 'bing', medium: 'cpc' }; if (attribution.twclid) return { source: 'twitter', medium: 'social' }; if (attribution.ttclid) return { source: 'tiktok', medium: 'social' }; if (attribution.li_fat_id) return { source: 'linkedin', medium: 'social' }; if (attribution.epik) return { source: 'pinterest', medium: 'social' }; if (attribution.gmb) return { source: 'google', medium: 'organic' }; // Check referrer if (document.referrer) { const referrerDomain = new URL(document.referrer).hostname; const currentDomain = window.location.hostname; if (referrerDomain !== currentDomain) { // Search engines if (referrerDomain.includes('google.')) return { source: 'google', medium: 'organic' }; if (referrerDomain.includes('bing.')) return { source: 'bing', medium: 'organic' }; if (referrerDomain.includes('yahoo.')) return { source: 'yahoo', medium: 'organic' }; if (referrerDomain.includes('duckduckgo.')) return { source: 'duckduckgo', medium: 'organic' }; // Social networks if (referrerDomain.includes('facebook.') || referrerDomain.includes('fb.')) return { source: 'facebook', medium: 'social' }; if (referrerDomain.includes('instagram.')) return { source: 'instagram', medium: 'social' }; if (referrerDomain.includes('twitter.') || referrerDomain === 'x.com') return { source: 'twitter', medium: 'social' }; if (referrerDomain.includes('linkedin.')) return { source: 'linkedin', medium: 'social' }; if (referrerDomain.includes('youtube.')) return { source: 'youtube', medium: 'social' }; // Other referral return { source: referrerDomain, medium: 'referral' }; } } return { source: 'direct', medium: 'none' }; } /** * Track enhanced conversion with source attribution and unique user detection */ function trackEnhancedConversion(eventName, conversionData) { // Check if this is a unique conversion for this user if (typeof UserFingerprint !== 'undefined') { const isUnique = UserFingerprint.isUniqueConversion(eventName); if (!isUnique && eventName === 'Schedule') { console.log('Duplicate conversion detected for user, skipping track'); return null; } } const attribution = getSourceAttribution(); const sourceMedium = determineSourceMedium(attribution); const sessionId = getSessionId(); // Get user fingerprint if available const userTracking = typeof UserFingerprint !== 'undefined' ? UserFingerprint.getUserTrackingInfo() : null; // Build enhanced event data const enhancedData = { ...conversionData, attribution: { source: sourceMedium.source, medium: sourceMedium.medium, campaign: attribution?.utm_campaign || attribution?.campaignid || '', term: attribution?.utm_term || attribution?.keyword || '', content: attribution?.utm_content || attribution?.creative || '', ...attribution }, session: { id: sessionId, landing_page: sessionStorage.getItem('efisio_landing_page') || window.location.href, page_count: parseInt(sessionStorage.getItem('efisio_page_count') || '1'), duration: Date.now() - parseInt(sessionStorage.getItem('efisio_session_start') || Date.now().toString()) }, user_fingerprint: userTracking ? userTracking.fingerprint : null, unique_user_id: userTracking ? userTracking.fingerprint.id : null, timestamp: new Date().toISOString() }; // Call the original evento function with enhanced data if (typeof evento === 'function') { evento(eventName, enhancedData); } return enhancedData; } /** * Track page view and update session */ function trackPageView() { // Store landing page if first page in session if (!sessionStorage.getItem('efisio_landing_page')) { sessionStorage.setItem('efisio_landing_page', window.location.href); sessionStorage.setItem('efisio_session_start', Date.now().toString()); } // Increment page count const pageCount = parseInt(sessionStorage.getItem('efisio_page_count') || '0') + 1; sessionStorage.setItem('efisio_page_count', pageCount.toString()); // Store source attribution storeSourceAttribution(); } /** * Enhanced schedule tracking */ function trackSchedule(appointmentData) { const { service, location, worker, price, promo } = appointmentData; return trackEnhancedConversion('Schedule', { currency: 'EUR', value: price || 35.0, service_id: service.id, service_name: service.name, location_id: location.id, location_name: location.name, worker_id: worker.id, worker_name: worker.name, promo_code: promo || '', appointment_start: appointmentData.start }); } /** * Initialize tracking on page load */ function init() { trackPageView(); } // Public API return { init: init, getSourceAttribution: getSourceAttribution, trackEnhancedConversion: trackEnhancedConversion, trackSchedule: trackSchedule, getSessionId: getSessionId }; })(); // Initialize on DOM ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', EnhancedTracking.init); } else { EnhancedTracking.init(); } // Generate or retrieve session ID for tracking user journey function getSessionId() { let sid = sessionStorage.getItem('efisio_session_id'); if (!sid) { sid = Date.now().toString(36) + Math.random().toString(36).substr(2, 9); sessionStorage.setItem('efisio_session_id', sid); } return sid; } function MyLogEventAPI(name, data, data2, callback) { var adata = { name: name, data: data, data2: data2, session_id: getSessionId(), ui: btoa(JSON.stringify(getAllUserInfo())), // "user_gaid": Cookie.readCookie("_ga") // Descomenta si necesitas esta línea y tienes implementada la función Cookie.readCookie }; fetch("/api/linfo", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(adata), }) .then((response) => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then((responseData) => { //console.log("logEventAPI Response", responseData); if (callback) callback(); }) .catch((error) => { console.error("logEventAPI ERROR", error.message); }); } function getParamFromURL(paramName) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(paramName) || null; } function getParamFromCookie(paramName) { // Get all cookies as an object const cookies = document.cookie.split(';').reduce((acc, cookie) => { const [key, value] = cookie.trim().split('='); acc[key] = value; return acc; }, {}); // Iterate over cookies for (const [key, value] of Object.entries(cookies)) { // Check if paramName exists in the cookie value if (value && value.includes(paramName)) { // Handle sbjs-like cookies with '|||' delimiter if (value.includes('|||')) { const parts = value.split('|||'); for (const part of parts) { if (part.includes(paramName)) { // Try to parse the part as a URL to extract query parameters try { const url = new URL(part.includes('://') ? part : `http://example.com?${part}`); const queryParams = new URLSearchParams(url.search); if (queryParams.has(paramName)) { return queryParams.get(paramName); } } catch (e) { // If part is not a valid URL, skip it continue; } } } } else { // Handle regular cookie value as a URL try { const url = new URL(value.includes('://') ? value : `http://example.com?${value}`); const queryParams = new URLSearchParams(url.search); if (queryParams.has(paramName)) { return queryParams.get(paramName); } } catch (e) { // If value is not a valid URL, skip it continue; } } } } // Return null if paramName is not found return null; } function evento(name, data, callback) { let dataobj = {}; // if user agent is adsbot, do not log if (navigator.userAgent.includes("adsbot")) { return; } // If array of two elements, first is label and second is value if (Array.isArray(data) && data.length === 2) { dataobj = { event_label: data[0], value: data[1] }; } else if (Array.isArray(data)) { dataobj = { arrayData: data }; } else if (typeof data === "object") { dataobj = data; } else if (typeof data === "string") { dataobj = { event_label: data }; } else if (typeof data === "number") { dataobj = { value: data }; } else if (typeof data === "boolean") { dataobj = { event_label: data ? "true" : "false" }; } else { dataobj = {}; } const eminfoCookie = getCookie("eminfo"); if (typeof gtag === "function") { if (eminfoCookie) { dataobj.user_data = { email_address: eminfoCookie }; } const gclid = getParamFromCookie('gclid') || getParamFromURL('gclid'); const gbraid = getParamFromCookie('gbraid') || getParamFromURL('gbraid'); const wbraid = getParamFromCookie('wbraid') || getParamFromURL('wbraid'); if (gclid) { dataobj.user_data = dataobj.user_data || {}; dataobj.user_data.gclid = gclid; } if (gbraid) { dataobj.user_data = dataobj.user_data || {}; dataobj.user_data.gbraid = gbraid; } if (wbraid) { dataobj.user_data = dataobj.user_data || {}; dataobj.user_data.wbraid = wbraid; } gtag("event", name, { ...dataobj }); } if (typeof fbq === "function") { if (eminfoCookie) { dataobj.em = eminfoCookie; const fbclid = getParamFromCookie('fbclid'); if (fbclid) { dataobj.fbclid = fbclid; } } let fbname = name; if (name === "Schedule") { fbname = "NuevaCita"; } // Add conversion values for Meta Ads optimization let fbdata = { ...dataobj }; if (fbname === "NuevaCita") { fbdata.value = 30.00; fbdata.currency = "EUR"; } else if (fbname === "IniciaWhatsapp" || fbname === "IniciaLlamada") { fbdata.value = 15.00; fbdata.currency = "EUR"; } else if (fbname === "EnviadoCV") { fbdata.value = 50.00; fbdata.currency = "EUR"; } fbq("trackCustom", fbname, fbdata); } // if event_label is set if (dataobj.event_label && dataobj.event_label.length > 0) { if (Array.isArray(data) && data.length === 2) { MyLogEventAPI(name, dataobj.event_label, dataobj.value, callback); } else { MyLogEventAPI(name, dataobj.event_label, dataobj, callback); } } else { MyLogEventAPI(name, dataobj, {}, callback); } } (function (f, b, e, v, n, t, s) { if (f.fbq) return; n = f.fbq = function () { n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments); }; if (!f._fbq) f._fbq = n; n.push = n; n.loaded = !0; n.version = "2.0"; n.queue = []; setTimeout(function () { t = b.createElement(e); t.async = !0; t.src = v; t.onload = function () { while (n.queue.length) { var args = n.queue.shift(); n.callMethod ? n.callMethod.apply(n, args) : n.queue.push(args); } fbq( "init", "2505138156445162", { em: "rim@efisio.es", fn: "rim", ln: "carranza", }, { agent: "efisioapps", } ); fbq("track", "PageView", []); }; s = b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t, s); }, 3000); })( window, document, "script", "https://connect.facebook.net/en_US/fbevents.js" ); function getLocationsByDistance(param, service) { // if param is array, then is coords if (Array.isArray(param)) { // join with comma param = param.join(","); } else { evento("Search", ["postalcode", param]); } return fetch("/api/get_near_locations/" + param) .then((response) => { return response.json(); }) .then((res) => { const alllocations = res.result; if (service) { service = parseInt(service); let locations = []; for (const l of alllocations) { if (l.ps.includes(service)) locations.push(l); } return locations; } else { return alllocations; } }); } document.addEventListener("DOMContentLoaded", function () { var $ = jQuery; $(".loginForm").on("submit", function (event) { event.preventDefault(); // Prevent the default form submission perform_login(this); // Call the perform_login function }); function perform_login(form, from = "") { console.log("perform_login", form); let previousPage = from; // if current page path does not contains "/cuenta/entrar", then previousPage is current page if ( previousPage == "" && !window.location.pathname.includes("/cuenta/entrar") ) { previousPage = window.location.pathname; } // if previousPage is empty, then previousPage is document.referrer if (previousPage == "") previousPage = document.referrer; // Obtener los valores de entrada de formulario const el = $(form).find('input[name="email"]'); let email = el.val(); // Trim leading and trailing white spaces email = email.trim(); email = email.toLowerCase(); email = email.replace(/^\.+|\.+$/g, ""); // If empty, show error if (email == "") { DialogConfirm("Por favor, introduce tu email o nombre de usuario."); return; } el.prop("disabled", true); let ls = $(form).find(".loginstatus"); ls.html("Enviando código de acceso..."); // Crear el objeto de credenciales de inicio de sesión const credentials = { email: email, redirect: previousPage, }; // Convertir el objeto de credenciales a formato JSON const jsonPayload = JSON.stringify(credentials); // Enviar la solicitud POST al endpoint de inicio de sesión $.ajax({ url: "/api/cuenta/entrar", type: "POST", contentType: "application/json", data: jsonPayload, success: function (data) { console.log(data); // Manejar la respuesta del inicio de sesión if (data.success) { // Inicio de sesión exitoso, realizar las acciones necesarias console.log("Inicio de sesión exitoso"); let url = "/cuenta/validar"; if (data.newuser) { url = "/cuenta/validar?newuser=1"; } // Redirigir al usuario o mostrar un mensaje de éxito window.location.href = url; return; } else { // Inicio de sesión fallido, mostrar mensaje de error console.error("Inicio de sesión fallido:", data.error); // Mostrar un mensaje de error al usuario ls.html(""); // Clear input email el.val(""); DialogConfirm(data.error); } el.prop("disabled", false); }, error: function (error) { // Manejar cualquier error de red o servidor console.error("Error:", error); // Mostrar un mensaje de error al usuario ls.html("Error al enviar el código de acceso."); }, }); } }); function setVisitInfo() { let days = 7; let previousPage = window.location.pathname; // append also parameters if (window.location.search) { previousPage += window.location.search; } let visitInfo = getUserInfo("visitInfo", {}); setCookie("previousPage", previousPage, days); visitInfo.previousPage = previousPage; // if not /citas/ in previousPage cookie, save beforeCitasPage cookie if ( previousPage.indexOf("/citas/") === -1 && previousPage.indexOf("/asistente/") === -1 ) { setCookie("beforeCitasPage", getCookie("previousPage"), days); visitInfo.beforeCitasPage = getCookie("previousPage"); } // if not firstPage cookie exists, create it if (!getCookie("firstPage")) { setCookie("firstPage", previousPage, days); visitInfo.firstPage = previousPage; } setUserInfo("visitInfo", visitInfo); } document.addEventListener("DOMContentLoaded", function () { var $ = jQuery; setVisitInfo(); // log Page View MyLogEventAPI("View", window.location.href); // on grantedCookies event, call setVisitInfo $(document).on("grantedCookies", function () { setVisitInfo(); MyLogEventAPI("GrantedCookies", window.location.href); }); }); function generatePdf(element) { Promise.all([ loadScript( "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js" ), loadScript( "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js" ), ]) .then(() => { console.log("Both html2canvas and jsPDF have been loaded"); // After loading the jspdf library, set it to the window object window.jsPDF = window.jspdf.jsPDF; if (element) { html2canvas(element, { scale: 2 }).then((canvas) => { const imgData = canvas.toDataURL("image/png"); const pdf = new jsPDF({ orientation: "p", unit: "mm", format: "a4", }); const imgProps = pdf.getImageProperties(imgData); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, "PNG", 0, 0, pdfWidth, pdfHeight); pdf.save("download.pdf"); }); } else { console.error("Element with id " + elementId + " not found."); } }) .catch((error) => { console.error("Error loading scripts: ", error); }); } function compareTwoStrings(first, second) { if (!first || first.length == 0 || !second || second.length == 0) return 0; // to lower case and remove accents first = first.toLowerCase(); second = second.toLowerCase(); first = first.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); second = second.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); first = first.replace(/\s+/g, ""); second = second.replace(/\s+/g, ""); if (first === second) return 1; // identical or empty if (first.length < 2 || second.length < 2) return 0; // if either is a 0-varter or 1-varter string var firstBigrams = new Map(); for (var i = 0; i < first.length - 1; i++) { const bigram = first.substring(i, i + 2); const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) + 1 : 1; firstBigrams.set(bigram, count); } var intersectionSize = 0; for (var i = 0; i < second.length - 1; i++) { const bigram = second.substring(i, i + 2); const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) : 0; if (count > 0) { firstBigrams.set(bigram, count - 1); intersectionSize++; } } var rank = (2.0 * intersectionSize) / (first.length + second.length - 2); if (second.includes(first) || first.includes(second)) { rank += 1; } return rank; } function findBestMatch(mainString, targetStrings) { if (!areArgsValid(mainString, targetStrings)) throw new Error( "Bad arguments: First argument should be a string, second should be an array of strings" ); const ratings = []; var bestMatchIndex = 0; for (var i = 0; i < targetStrings.length; i++) { const currentTargetString = targetStrings[i]; let currentRating = compareTwoStrings(mainString, currentTargetString); ratings.push({ target: currentTargetString, rating: currentRating }); if (currentRating > ratings[bestMatchIndex].rating) { bestMatchIndex = i; } } ratings.sort((a, b) => b.rating - a.rating); // Sort ratings in descending order // Get top results with rating over 0.5 let topResults = ratings.filter((r) => r.rating > 1); // If empty, get top results with rating over 0.2 if (!topResults.length) { topResults = ratings.filter((r) => r.rating > 0.05); } // If empty, get top results with rating over 0 if (!topResults.length) { topResults = ratings.filter((r) => r.rating > 0); } // keep top 10 topResults = topResults.slice(0, 10); const bestMatch = ratings[bestMatchIndex]; return { ratings: ratings, bestMatch: bestMatch, bestMatchIndex: bestMatchIndex, topResults: topResults, }; } function areArgsValid(mainString, targetStrings) { if (typeof mainString !== "string") return false; if (!Array.isArray(targetStrings)) return false; if (!targetStrings.length) return false; if ( targetStrings.find(function (s) { return typeof s !== "string"; }) ) return false; return true; } /** * User Fingerprinting System * Creates unique user identifiers combining multiple data points */ var UserFingerprint = (function() { 'use strict'; /** * Generate a stable hash from string */ function simpleHash(str) { var hash = 0; if (str.length === 0) return hash; for (var i = 0; i < str.length; i++) { var char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32bit integer } return Math.abs(hash).toString(36); } /** * Get browser fingerprint components */ function getBrowserFingerprint() { var components = []; // Screen resolution components.push(screen.width + 'x' + screen.height); // Timezone offset components.push(new Date().getTimezoneOffset()); // Language components.push(navigator.language || navigator.userLanguage || 'unknown'); // Platform components.push(navigator.platform || 'unknown'); // User agent (simplified) var ua = navigator.userAgent || ''; var uaSimplified = ua.replace(/\d+\.\d+\.\d+/g, '').replace(/\s+/g, ' '); components.push(simpleHash(uaSimplified)); // Available fonts (basic check) var testString = "mmmmmmmmmmlli"; var testSize = '72px'; var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); context.textBaseline = 'top'; context.font = testSize + ' monospace'; var baselineWidth = context.measureText(testString).width; components.push(baselineWidth.toString()); // Canvas fingerprint (basic) canvas.width = 200; canvas.height = 50; context.textBaseline = 'alphabetic'; context.fillStyle = '#f60'; context.fillRect(125, 1, 62, 20); context.fillStyle = '#069'; context.font = '11pt Arial'; context.fillText('Efisio.es 🔍', 2, 15); context.fillStyle = 'rgba(102, 204, 0, 0.7)'; context.font = '18pt Arial'; context.fillText('Efisio', 4, 45); var canvasHash = simpleHash(canvas.toDataURL()); components.push(canvasHash); return components.join('|'); } /** * Get Google Analytics Client ID if available */ function getGoogleAnalyticsId() { // Try to get GA4 Client ID if (typeof gtag === 'function') { try { var clientId = null; gtag('get', 'GA_MEASUREMENT_ID', 'client_id', function(id) { clientId = id; }); if (clientId) return clientId; } catch (e) { // Silent fail } } // Try to get from GA cookie var gaCookie = getCookie('_ga'); if (gaCookie) { var parts = gaCookie.split('.'); if (parts.length >= 4) { return parts[2] + '.' + parts[3]; } } return null; } /** * Get Facebook Pixel ID if available */ function getFacebookPixelId() { var fbpCookie = getCookie('_fbp'); if (fbpCookie) { return fbpCookie; } // Try to get from fbq if available if (typeof fbq === 'function' && fbq._fbp) { return fbq._fbp; } return null; } /** * Generate or retrieve persistent user ID */ function getPersistentUserId() { var storageKey = 'efisio_user_id'; // Try localStorage first var storedId = localStorage.getItem(storageKey); if (storedId) { return storedId; } // Try sessionStorage storedId = sessionStorage.getItem(storageKey); if (storedId) { localStorage.setItem(storageKey, storedId); return storedId; } // Try cookie storedId = getCookie('efisio_uid'); if (storedId) { localStorage.setItem(storageKey, storedId); return storedId; } // Generate new ID var newId = 'uid_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); // Store in multiple places localStorage.setItem(storageKey, newId); sessionStorage.setItem(storageKey, newId); setCookie('efisio_uid', newId, 365 * 2); // 2 years return newId; } /** * Create comprehensive user fingerprint */ function createUserFingerprint() { var components = []; // 1. Persistent user ID (most reliable) var persistentId = getPersistentUserId(); components.push('pid:' + persistentId); // 2. Google Analytics ID (if available) var gaId = getGoogleAnalyticsId(); if (gaId) { components.push('ga:' + gaId); } // 3. Facebook Pixel ID (if available) var fbId = getFacebookPixelId(); if (fbId) { components.push('fb:' + fbId); } // 4. Browser fingerprint var browserFp = getBrowserFingerprint(); components.push('br:' + simpleHash(browserFp)); // Create final fingerprint hash var finalHash = simpleHash(components.join('|')); return { id: finalHash, persistent_id: persistentId, ga_id: gaId, fb_id: fbId, browser_fingerprint: simpleHash(browserFp), components: components.length }; } /** * Get or create user session fingerprint (shorter lived) */ function getSessionFingerprint() { var sessionKey = 'efisio_session_fp'; var stored = sessionStorage.getItem(sessionKey); if (stored) { return JSON.parse(stored); } var fingerprint = createUserFingerprint(); fingerprint.session_start = Date.now(); fingerprint.page_count = 1; sessionStorage.setItem(sessionKey, JSON.stringify(fingerprint)); return fingerprint; } /** * Update session page count */ function updateSessionPageCount() { var sessionKey = 'efisio_session_fp'; var stored = sessionStorage.getItem(sessionKey); if (stored) { var fingerprint = JSON.parse(stored); fingerprint.page_count = (fingerprint.page_count || 0) + 1; fingerprint.last_activity = Date.now(); sessionStorage.setItem(sessionKey, JSON.stringify(fingerprint)); return fingerprint; } return getSessionFingerprint(); } /** * Check if this is a unique conversion (hasn't converted in this session) */ function isUniqueConversion(eventType) { var conversionKey = 'efisio_conversions'; var stored = sessionStorage.getItem(conversionKey); var conversions = stored ? JSON.parse(stored) : {}; var fingerprint = getSessionFingerprint(); var userId = fingerprint.id; if (!conversions[userId]) { conversions[userId] = []; } // Check if this event type already exists for this user in this session var alreadyConverted = conversions[userId].includes(eventType); if (!alreadyConverted) { conversions[userId].push(eventType); sessionStorage.setItem(conversionKey, JSON.stringify(conversions)); } return !alreadyConverted; } /** * Get user info for tracking */ function getUserTrackingInfo() { var fingerprint = updateSessionPageCount(); var userInfo = getAllUserInfo(); return { fingerprint: fingerprint, user_info: userInfo, cookies: { firstPage: getCookie('firstPage'), previousPage: getCookie('previousPage'), beforeCitasPage: getCookie('beforeCitasPage'), _ga: getCookie('_ga'), _gcl_au: getCookie('_gcl_au'), _fbp: getCookie('_fbp'), _fbc: getCookie('_fbc') }, timestamp: Date.now() }; } // Public API return { createFingerprint: createUserFingerprint, getSessionFingerprint: getSessionFingerprint, updatePageCount: updateSessionPageCount, isUniqueConversion: isUniqueConversion, getUserTrackingInfo: getUserTrackingInfo, getPersistentId: getPersistentUserId }; })(); // Auto-initialize on load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { UserFingerprint.updatePageCount(); }); } else { UserFingerprint.updatePageCount(); } function isValidPhone(phone) { const result = /^(\+?\d{1,3})?\d{8,14}$/.test(phone); return result; } /** * Validate Spanish NIF/NIE/CIF format * @param {string} nif - The NIF/NIE/CIF to validate * @returns {boolean} True if valid, false otherwise */ function isValidNIF(nif) { if (!nif || !nif.length) return false; // Normalize: uppercase, no spaces nif = nif.toUpperCase().replace(/\s+/g, ''); // Check basic format if (!/^[A-Z0-9]{9}$/.test(nif)) return false; // Validate NIF (DNI) if (/^[0-9]{8}[A-Z]$/.test(nif)) { const letters = 'TRWAGMYFPDXBNJZSQVHLCKE'; const number = parseInt(nif.substring(0, 8), 10); const letter = nif.charAt(8); return letters.charAt(number % 23) === letter; } // Validate NIE if (/^[XYZ][0-9]{7}[A-Z]$/.test(nif)) { const letters = 'TRWAGMYFPDXBNJZSQVHLCKE'; let nieNumber = nif.substring(1, 8); const firstChar = nif.charAt(0); // Replace X, Y, Z with 0, 1, 2 if (firstChar === 'X') nieNumber = '0' + nieNumber; else if (firstChar === 'Y') nieNumber = '1' + nieNumber; else if (firstChar === 'Z') nieNumber = '2' + nieNumber; const number = parseInt(nieNumber, 10); const letter = nif.charAt(8); return letters.charAt(number % 23) === letter; } // Validate CIF (basic format check, full validation is complex) if (/^[ABCDEFGHJNPQRSUVW][0-9]{7}[0-9A-J]$/.test(nif)) { return true; // Simplified CIF validation } // Accept passport format for foreigners (at least 8 alphanumeric characters) if (/^[A-Z0-9]{8,}$/.test(nif)) { return true; } return false; } function callErrorAPI(error) { // Define your API endpoint const apiEndpoint = "/api/error-logger"; // Set up the data you want to send, including the error message const data = { errorMessage: error.message, stackTrace: error.stack, }; const extraAgents = ["facebookexternalhit", "ia_archiver"]; if ( !navigator.userAgent.toLowerCase().includes("bot") && !extraAgents.some((agent) => navigator.userAgent.includes(agent)) ) { // Use fetch API to send the error details to your endpoint fetch(apiEndpoint, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data), }) .then((response) => response.json()) .then((data) => { }) .catch((error) => { console.error("Error:", error); }); } } window.onerror = function (message, source, lineno, colno, error) { // Log the error details to the console console.error( "An error occurred:", message, "Source:", source, "Line:", lineno, "Column:", colno, "Error object:", error ); // Call your API with the error information callErrorAPI(error); // Return true to prevent the default browser error handler return true; }; window.addEventListener("unhandledrejection", function (event) { console.error( "Unhandled rejection (promise: ", event.promise, ", reason: ", event.reason, ")." ); callErrorAPI(event.reason); }); window.loadScript = (url) => { return new Promise((resolve, reject) => { let script = document.createElement("script"); script.type = "text/javascript"; script.onload = resolve; script.onerror = reject; script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }); }; window.loadStyle = (url) => { return new Promise((resolve, reject) => { let link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; link.onload = resolve; link.onerror = reject; link.href = url; document.getElementsByTagName("head")[0].appendChild(link); }); }; // Función para guardar eventos en el localStorage function getAllUserInfo() { let ui = JSON.parse(localStorage.getItem("ui")); if (!ui) { ui = {}; } return ui; } function getUserInfo(key, defaultValue = null) { let ui = getAllUserInfo(); if (ui && ui[key]) { return ui[key]; } else { return defaultValue; } } function setUserInfo(key, value) { let ui = getAllUserInfo(); ui[key] = value; localStorage.setItem("ui", JSON.stringify(ui)); } function saveEvent(eventData) { let events = getUserInfo("events", []); events.push(eventData); setUserInfo("events", events); } function sendEvents() { let events = getUserInfo("events", []); fetch("/api/user-info", { method: "POST", body: JSON.stringify(events), }); } function checkCookieConsent() { const consentCookie = getCookie("CookieLawInfoConsent"); if (consentCookie) { return JSON.parse(atob(consentCookie)); } return null; } function setCookieConsent(value) { const encodedValue = btoa(JSON.stringify(value)); setCookie("CookieLawInfoConsent", encodedValue, 365, true); // Setting the cookie to expire in 1 year } function areNecessaryCookiesAccepted() { const consent = checkCookieConsent(); return consent && consent.necessary; } function areAdvertisementCookiesAccepted() { const consent = checkCookieConsent(); return consent && consent.advertisement; } function setCookie(name, value, days, force) { setCookieSeconds(name, value, days * 24 * 60 * 60, force); } function setCookieSeconds(name, value, seconds, force) { let expires = ""; if (seconds) { if (!areNecessaryCookiesAccepted() && !force) { return; } const date = new Date(); date.setTime(date.getTime() + seconds * 1000); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + (value || "") + expires + "; path=/"; } // Get a cookie by name function getCookie(name) { const value = "; " + document.cookie; const parts = value.split("; " + name + "="); if (parts.length === 2) return parts.pop().split(";").shift(); } function GenericDialog( text, buttons = [], options = { prepend: false, default_class: "modal" } ) { // Create a container div const modalDiv = document.createElement("div"); modalDiv.classList.add(options.default_class); modalDiv.id = "cucu-" + Math.random(); // Set the innerHTML of the container div to your HTML content modalDiv.innerHTML = `
${text}
`; // For each button, create a button element and append it to the container div buttons.forEach((button) => { const btn = document.createElement("button"); btn.innerText = button[0]; if (button[1].length) btn.classList.add(button[1]); btn.onclick = () => { button[2](btn); }; modalDiv.querySelector(".modal_btns").appendChild(btn); }); if (options.prepend) document.body.prepend(modalDiv); else document.body.appendChild(modalDiv); // Activate the modal after a short delay setTimeout(() => { modalDiv.classList.add("active"); }, 10); return modalDiv; } function closeAndRemoveModal(btn, parent_class = ".modal") { var modal = null; if (btn) modal = btn.closest(parent_class); // Find parent modal of this else modal = $(this).closest(parent_class); modal.classList.remove("active"); //setTimeout(() => { modal.remove(); //}, 1000); } function DialogConfirm(text, callback) { return GenericDialog(text, [ [ "Ok", "", (btn) => { closeAndRemoveModal(btn); if (callback) callback(); }, ], ]); } function UserConfirm(text, callbackOk, callbackCancel) { return GenericDialog(text, [ [ "Ok", "", (btn) => { closeAndRemoveModal(btn); if (callbackOk) callbackOk(); }, ], [ "Cancelar", "secondary", (btn) => { closeAndRemoveModal(btn); if (callbackCancel) callbackCancel(); }, ], ]); } function DialogIndicator(text) { let content = `
${text}
`; let indicator = GenericDialog(content, []); return { indicator, close: () => { closeAndRemoveModal(indicator); }, }; } function BottomNotification(text, buttons, callbackOk = null) { return GenericDialog(text, buttons, { default_class: "bottom_notification" }); } function AskForInput(title, placeholder = "", defaultValue = "") { return new Promise((resolve, reject) => { const inputHtml = `
${title}
`; const dialog = GenericDialog(inputHtml, [ [ "Ok", "primary", (btn) => { const input = btn.closest('.modal').querySelector('input'); const value = input.value.trim(); closeAndRemoveModal(btn); resolve(value); }, ], [ "Cancelar", "secondary", (btn) => { closeAndRemoveModal(btn); reject(); }, ], ]); // Focus the input field after dialog is shown setTimeout(() => { const input = dialog.querySelector('input'); input.focus(); }, 100); }); } document.addEventListener("DOMContentLoaded", () => { document.addEventListener("click", function (event) { // Handler for [data-close-panel] const closePanelButton = event.target.closest("[data-close-panel]"); if (closePanelButton) { const vpanelElement = closePanelButton.closest(".vpanel"); if (vpanelElement) { toggleVPanel(vpanelElement, false); } } // Handler for [data-close-modal] const closeModalButton = event.target.closest("[data-close-modal]"); if (closeModalButton) { const modalElement = closeModalButton.closest(".modal"); if (modalElement) { toggleVPanel(modalElement, false); } } }); }); function toggleModal(modal) { let modalElement = document.querySelector(modal); if (modalElement.classList.contains("active")) { modalElement.classList.remove("active"); } else { modalElement.classList.add("active"); } } function toggleVPanel(s, enable) { const element = (typeof s === 'string') ? document.querySelector(s) : s; if (!element) { return; } if (element.classList.contains("active")) { if (enable !== true) { element.classList.remove("active"); } } else { document.querySelectorAll(".vpanel.active").forEach(activePanel => { activePanel.classList.remove("active"); }); element.classList.add("active"); } } function getWindowDimensions() { var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName("body")[0], x = w.innerWidth || e.clientWidth || g.clientWidth, y = w.innerHeight || e.clientHeight || g.clientHeight; return { width: x, height: y }; } document.addEventListener("DOMContentLoaded", function () { var $ = jQuery; function positionDropdown() { var w = getWindowDimensions(); var m = _this.root.querySelector(".menu"); if (!m) return; if (!opts.select.isvisible) { m.style.marginTop = ""; m.style.marginLeft = ""; return; } var pos = m.getBoundingClientRect(); if (w.width < pos.left + pos.width) { m.style.marginLeft = w.width - (pos.left + pos.width) - 20 + "px"; } if (pos.left < 0) { m.style.marginLeft = "20px"; } if (w.height < pos.top + pos.height) { m.style.marginTop = w.height - (pos.top + pos.height) - 20 + "px"; } } function positionDropdownRelativeToParent(parent, popup) { var w = getWindowDimensions(); var m = popup; if (!m) return; var parent_pos = parent.getBoundingClientRect(); var pos = m.getBoundingClientRect(); /* console.log("Window: ", w); console.log("Parent: ", parent_pos); console.log("Popup Before: ", pos); */ let left = 0; if (pos.width > w.width) { m.style.width = w.width; } else { if (parent_pos.left + parent_pos.width > w.width) { if (parent_pos.right > pos.width) left = parent_pos.right - pos.width; else left = w.width - pos.width; } else { left = parent_pos.left; } $(m).width(parent_pos.width); } m.style.zIndex = parent.style.zIndex + 1; let top = $(parent).offset().top + $(parent).outerHeight(); $(m).offset({ top: top, left: left, }); // Max height should be top position minus window height var max_height = w.height - (w.height - top); } $(document).on("click", ".popup2", function (e) { e.stopPropagation(); // if it has class active, remove it if ($(this).hasClass("active")) { $(this).removeClass("active"); } }); $(document).on("click", ".popup2 .content", function (e) { e.stopPropagation(); }); $(document).on("click", "*[toggle-popup2]", function (e) { console.log("PARENT", this); var s = $(e.currentTarget).attr("toggle-popup2"); var popup_container = $(s)[0]; var popup = $(s).find(".content")[0]; console.log("POPUP", popup); positionDropdownRelativeToParent(this, popup); if ($(popup_container).hasClass("active")) { $(popup_container).removeClass("active"); } else { $(popup_container).addClass("active"); } }); }); function isMobileApp() { // Check if user agent is var is_mobile_app = navigator.userAgent.indexOf("efisioios") !== -1 || navigator.userAgent.indexOf("efisioandroid") !== -1; return is_mobile_app; } function removeAccents(str) { return str .toLowerCase() .normalize("NFD") // Decompose accented characters into their base character and accompanying diacritic mark .replace(/[\u0300-\u036f]/g, ""); // Remove the diacritic marks } document.addEventListener("click", function(e) { var el = e.target.closest("[data-toggle-w]"); if (el) { e.preventDefault(); var sel = el.getAttribute("data-toggle-w"); var target = document.querySelector(sel); if (!target) return; if (target.style.width && target.style.width !== "0px" && target.style.width !== "0") { target.style.width = "0"; } else { target.style.width = "100vw"; } } var el2 = e.target.closest("[data-toggle-h]"); if (el2) { e.preventDefault(); var sel2 = el2.getAttribute("data-toggle-h"); if (typeof toggleVPanel === "function") { toggleVPanel(sel2); } else { var target2 = document.querySelector(sel2); if (target2) target2.classList.toggle("active"); } } });